home *** CD-ROM | disk | FTP | other *** search
- Path: uunet!bbn.com!rsalz
- From: rsalz@uunet.uu.net (Rich Salz)
- Newsgroups: comp.sources.unix
- Subject: v18i075: MIT Athena delete/undelete programs, Part03/06
- Message-ID: <1635@fig.bbn.com>
- Date: 29 Mar 89 04:32:02 GMT
- Lines: 750
- Approved: rsalz@uunet.UU.NET
-
- Submitted-by: Jonathan I. Kamens <jik@PIT-MANAGER.MIT.EDU>
- Posting-number: Volume 18, Issue 75
- Archive-name: undel/part03
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of archive 3 (of 6)."
- # Contents: delete.c lsdel.c
- # Wrapped by jik@pit-manager on Mon Mar 27 12:16:50 1989
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'delete.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'delete.c'\"
- else
- echo shar: Extracting \"'delete.c'\" \(9801 characters\)
- sed "s/^X//" >'delete.c' <<'END_OF_FILE'
- X/*
- X * $Source: /mit/jik/src/delete/RCS/delete.c,v $
- X * $Author: jik $
- X *
- X * This program is a replacement for rm. Instead of actually deleting
- X * files, it marks them for deletion by prefixing them with a ".#"
- X * prefix.
- X *
- X * Copyright (c) 1989 by the Massachusetts Institute of Technology.
- X * For copying and distribution information, see the file "mit-copyright.h."
- X */
- X
- X#if (!defined(lint) && !defined(SABER))
- X static char rcsid_delete_c[] = "$Header: delete.c,v 1.17 89/03/27 12:05:58 jik Exp $";
- X#endif
- X
- X#include <sys/types.h>
- X#include <stdio.h>
- X#include <sys/stat.h>
- X#include <sys/dir.h>
- X#include <strings.h>
- X#include <sys/param.h>
- X#include <sys/file.h>
- X#include "util.h"
- X#include "delete.h"
- X#include "mit-copyright.h"
- X
- X
- X
- X
- X/*
- X * ALGORITHM:
- X *
- X * 1. Parse command-line arguments and set flags.
- X * 2. Call the function delete() for each filename command-line argument.
- X *
- X * delete():
- X *
- X * 1. Can the file be lstat'd?
- X * no -- abort
- X * yes -- continue
- X * 2. Is the file a directory?
- X * yes -- is it a dotfile?
- X * yes -- abort
- X * no -- continue
- X * -- is the filesonly option set?
- X * yes -- is the recursive option specified?
- X * yes -- continue
- X * no -- abort
- X * no -- is the directory empty?
- X * yes -- remove it
- X * no -- is the directoriesonly option set?
- X * yes -- abort
- X * no -- continue
- X * -- is the recursive option specified?
- X * yes -- continue
- X * no -- abort
- X * no -- is the directoriesonly option set?
- X * yes -- abort
- X * no -- continue
- X * 3. If the file is a file, remove it.
- X * 4. If the file is a directory, open it and pass each of its members
- X * (excluding . files) to delete().
- X */
- X
- X
- Xint force, interactive, recursive, noop, verbose, filesonly, directoriesonly;
- Xchar *whoami;
- Xchar *malloc();
- X
- Xmain(argc, argv)
- Xint argc;
- Xchar *argv[];
- X{
- X extern char *optarg;
- X extern int optind;
- X int arg;
- X int status = 0;
- X
- X whoami = lastpart(argv[0]);
- X
- X force = interactive = recursive = noop = verbose = filesonly =
- X directoriesonly = 0;
- X while ((arg = getopt(argc, argv, "firnvFD")) != -1) {
- X switch (arg) {
- X case 'r':
- X recursive++;
- X if (directoriesonly) {
- X fprintf(stderr, "%s: -r and -D are mutually exclusive.\n",
- X whoami);
- X usage();
- X exit(! force);
- X }
- X break;
- X case 'f':
- X force++;
- X break;
- X case 'i':
- X interactive++;
- X break;
- X case 'n':
- X noop++;
- X break;
- X case 'v':
- X verbose++;
- X break;
- X case 'F':
- X filesonly++;
- X if (directoriesonly) {
- X fprintf(stderr, "%s: -F and -D are mutually exclusive.\n",
- X whoami);
- X usage();
- X exit(! force);
- X }
- X break;
- X case 'D':
- X directoriesonly++;
- X if (recursive) {
- X fprintf(stderr, "%s: -r and -D are mutually exclusive.\n",
- X whoami);
- X usage();
- X exit(! force);
- X }
- X if (filesonly) {
- X fprintf(stderr, "%s: -F and -D are mutually exclusive.\n",
- X whoami);
- X usage();
- X exit(! force);
- X }
- X break;
- X default:
- X usage();
- X exit(! force);
- X }
- X }
- X if (optind == argc) {
- X fprintf(stderr, "%s: no files specified.\n", whoami);
- X usage();
- X exit(! force);
- X }
- X while (optind < argc) {
- X status = status | delete(argv[optind], 0);
- X optind++;
- X }
- X exit((! force) && (status & ERROR_MASK));
- X}
- X
- X
- X
- X
- Xusage()
- X{
- X printf("Usage: %s [ options ] filename ...\n", whoami);
- X printf("Options are:\n");
- X printf(" -r recursive\n");
- X printf(" -i interactive\n");
- X printf(" -f force\n");
- X printf(" -n noop\n");
- X printf(" -v verbose\n");
- X printf(" -F files only\n");
- X printf(" -D directories only\n");
- X printf(" -- end options and start filenames\n");
- X printf("-r and -D are mutually exclusive\n");
- X printf("-F and -D are mutually exclusive\n");
- X}
- X
- X
- X
- X
- X
- X
- Xdelete(filename, recursed)
- Xchar *filename;
- Xint recursed;
- X{
- X struct stat stat_buf;
- X
- X /* can the file be lstat'd? */
- X if (lstat(filename, &stat_buf) == -1) {
- X if (! force)
- X fprintf(stderr, "%s: %s nonexistent\n", whoami, filename);
- X return(ERROR_MASK);
- X }
- X
- X /* is the file a directory? */
- X if ((stat_buf.st_mode & S_IFMT) == S_IFDIR) {
- X /* is the file a dot file? */
- X if (is_dotfile(filename)) {
- X if (! force)
- X fprintf(stderr, "%s: cannot remove `.' or `..'\n",
- X whoami);
- X return(ERROR_MASK);
- X }
- X /* is the filesonly option set? */
- X if (filesonly) {
- X /* is the recursive option specified? */
- X if (recursive) {
- X return(recursive_delete(filename, stat_buf, recursed));
- X }
- X else {
- X if (! force)
- X fprintf(stderr, "%s: %s directory\n", whoami,
- X filename);
- X return(ERROR_MASK);
- X }
- X }
- X else {
- X /* is the directory empty? */
- X if (empty_directory(filename)) {
- X /* remove it */
- X return(do_move(filename, stat_buf, 0));
- X }
- X else {
- X /* is the directoriesonly option set? */
- X if (directoriesonly) {
- X if (! force)
- X fprintf(stderr, "%s: %s: Directory not empty\n",
- X whoami, filename);
- X return(ERROR_MASK);
- X }
- X else {
- X /* is the recursive option specified? */
- X if (recursive) {
- X return(recursive_delete(filename, stat_buf,
- X recursed));
- X }
- X else {
- X if (! force)
- X fprintf(stderr, "%s: %s not empty\n",
- X whoami, filename);
- X return(ERROR_MASK);
- X }
- X }
- X }
- X }
- X }
- X else {
- X /* is the directoriesonly option set? */
- X if (directoriesonly) {
- X if (! force)
- X fprintf(stderr, "%s: %s: Not a directory\n", whoami,
- X filename);
- X return(ERROR_MASK);
- X }
- X else
- X return(do_move(filename, stat_buf, 0));
- X }
- X}
- X
- X
- X
- X
- Xempty_directory(filename)
- Xchar *filename;
- X{
- X DIR *dirp;
- X struct direct *dp;
- X
- X dirp = opendir(filename);
- X if (! dirp) {
- X return(0);
- X }
- X for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
- X if (is_dotfile(dp->d_name))
- X continue;
- X if (is_deleted(dp->d_name))
- X continue;
- X else {
- X closedir(dirp);
- X return(0);
- X }
- X }
- X closedir(dirp);
- X return(1);
- X}
- X
- X
- X
- X
- Xrecursive_delete(filename, stat_buf, recursed)
- Xchar *filename;
- Xstruct stat stat_buf;
- Xint recursed;
- X{
- X DIR *dirp;
- X struct direct *dp;
- X int status = 0;
- X char newfile[MAXPATHLEN];
- X
- X if (interactive && recursed) {
- X printf("%s: remove directory %s? ", whoami, filename);
- X if (! yes())
- X return(NO_DELETE_MASK);
- X }
- X dirp = opendir(filename);
- X if (! dirp) {
- X if (! force)
- X fprintf(stderr, "%s: %s not changed\n", whoami, filename);
- X return(ERROR_MASK);
- X }
- X for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
- X if (is_dotfile(dp->d_name))
- X continue;
- X if (is_deleted(dp->d_name))
- X continue;
- X else {
- X strcpy(newfile, append(filename, dp->d_name, !force));
- X if (*newfile)
- X status = status | delete(newfile, 1);
- X else
- X status = ERROR_MASK;
- X }
- X }
- X closedir(dirp);
- X status = status | do_move(filename, stat_buf, status);
- X return(status);
- X}
- X
- X
- X
- X
- X
- X
- Xdo_move(filename, stat_buf, err_mask)
- Xchar *filename;
- Xstruct stat stat_buf;
- Xint err_mask;
- X{
- X char *last;
- X char buf[MAXPATHLEN];
- X char name[MAXNAMLEN];
- X struct stat deleted_buf;
- X
- X strncpy(buf, filename, MAXPATHLEN);
- X last = lastpart(buf);
- X if (strlen(last) > MAXNAMLEN) {
- X if (! force)
- X fprintf(stderr, "%s: %s: filename too long\n", whoami,
- X filename);
- X return(ERROR_MASK);
- X }
- X strcpy(name, last);
- X if (strlen(buf) + 3 > MAXPATHLEN) {
- X if (! force)
- X fprintf(stderr, "%s: %s: pathname too long\n", whoami,
- X filename);
- X return(ERROR_MASK);
- X }
- X *last = '\0';
- X strcat(buf, ".#");
- X strcat(buf, name);
- X if (err_mask) {
- X if (! force)
- X fprintf(stderr, "%s: %s not removed\n", whoami, filename);
- X return(err_mask);
- X }
- X if (interactive) {
- X printf("%s: remove %s? ", whoami, filename);
- X if (! yes())
- X return(NO_DELETE_MASK);
- X }
- X else if ((! force) && ((stat_buf.st_mode & S_IFMT) != S_IFLNK)
- X && access(filename, W_OK)) {
- X printf("%s: override protection %o for %s? ", whoami,
- X stat_buf.st_mode & 0777, filename);
- X if (! yes())
- X return(NO_DELETE_MASK);
- X }
- X if (noop) {
- X fprintf(stderr, "%s: %s would be removed\n", whoami, filename);
- X return(0);
- X }
- X if (! lstat(buf, &deleted_buf))
- X unlink_completely(buf);
- X if (rename(filename, buf)) {
- X if (! force)
- X fprintf(stderr, "%s: %s not removed\n", whoami, filename);
- X return(ERROR_MASK);
- X }
- X else {
- X if (verbose)
- X fprintf(stderr, "%s: %s removed\n", whoami, filename);
- X return(0);
- X }
- X}
- X
- X
- X
- Xunlink_completely(filename)
- Xchar *filename;
- X{
- X char buf[MAXPATHLEN];
- X struct stat stat_buf;
- X DIR *dirp;
- X struct direct *dp;
- X int status = 0;
- X
- X if (lstat(filename, &stat_buf))
- X return(1);
- X
- X if ((stat_buf.st_mode & S_IFMT) == S_IFDIR) {
- X dirp = opendir(filename);
- X if (! dirp)
- X return(1);
- X readdir(dirp); readdir(dirp); /* get rid of . and .. */
- X for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
- X strcpy(buf, append(filename, dp->d_name, 0));
- X if (! buf) {
- X status = 1;
- X continue;
- X }
- X status = status | unlink_completely(buf);
- X }
- X closedir(dirp);
- X status = status | rmdir(filename);
- X return(status);
- X }
- X else
- X return(unlink(filename) == -1);
- X}
- X
- END_OF_FILE
- if test 9801 -ne `wc -c <'delete.c'`; then
- echo shar: \"'delete.c'\" unpacked with wrong size!
- fi
- # end of 'delete.c'
- fi
- if test -f 'lsdel.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'lsdel.c'\"
- else
- echo shar: Extracting \"'lsdel.c'\" \(6087 characters\)
- sed "s/^X//" >'lsdel.c' <<'END_OF_FILE'
- X/*
- X * $Source: /mit/jik/src/delete/RCS/lsdel.c,v $
- X * $Author: jik $
- X *
- X * This program is a replacement for rm. Instead of actually deleting
- X * files, it marks them for deletion by prefixing them with a ".#"
- X * prefix.
- X *
- X * Copyright (c) 1989 by the Massachusetts Institute of Technology.
- X * For copying and distribution information, see the file "mit-copyright.h."
- X */
- X
- X#if (!defined(lint) && !defined(SABER))
- X static char rcsid_lsdel_c[] = "$Header: lsdel.c,v 1.4 89/03/27 12:07:13 jik Exp $";
- X#endif
- X
- X#include <stdio.h>
- X#include <sys/types.h>
- X#include <sys/dir.h>
- X#include <sys/param.h>
- X#include <sys/stat.h>
- X#include <strings.h>
- X#include "col.h"
- X#include "util.h"
- X#include "directories.h"
- X#include "pattern.h"
- X#include "lsdel.h"
- X#include "mit-copyright.h"
- X
- Xchar *malloc(), *realloc();
- Xextern int current_time;
- X
- Xint block_total = 0;
- Xint dirsonly, recursive, timev, yield;
- Xchar *whoami, *error_buf;
- X
- Xmain(argc, argv)
- Xint argc;
- Xchar *argv[];
- X{
- X extern char *optarg;
- X extern int optind;
- X int arg;
- X
- X whoami = lastpart(argv[0]);
- X error_buf = malloc(strlen(whoami) + MAXPATHLEN + 3);
- X if (! error_buf) {
- X perror(whoami);
- X exit(1);
- X }
- X dirsonly = recursive = timev = yield = 0;
- X while ((arg = getopt(argc, argv, "drt:y")) != -1) {
- X switch (arg) {
- X case 'd':
- X dirsonly++;
- X break;
- X case 'r':
- X recursive++;
- X break;
- X case 't':
- X timev = atoi(optarg);
- X break;
- X case 'y':
- X yield++;
- X break;
- X default:
- X usage();
- X exit(1);
- X }
- X }
- X if (optind == argc) {
- X char *cwd;
- X
- X cwd = ".";
- X exit(ls(&cwd, 1));
- X }
- X exit(ls(&argv[optind], argc - optind));
- X}
- X
- X
- X
- X
- X
- X
- Xusage()
- X{
- X printf("Usage: %s [ options ] [ filename [ ...]]\n", whoami);
- X printf("Options are:\n");
- X printf(" -d list directory names, not contents\n");
- X printf(" -r recursive\n");
- X printf(" -t n list n-day-or-older files only\n");
- X printf(" -y report total space taken up by files\n");
- X}
- X
- X
- X
- X
- Xls(args, num)
- Xchar **args;
- Xint num;
- X{
- X char *start_dir;
- X char **found_files;
- X int num_found, total = 0;
- X char *file_re;
- X int status = 0;
- X
- X if (initialize_tree())
- X exit(1);
- X
- X for ( ; num; num--) {
- X if (*args[num - 1] == '/') {
- X start_dir = "/";
- X file_re = parse_pattern(args[num - 1] + 1);
- X }
- X else {
- X start_dir = "";
- X file_re = parse_pattern(args[num - 1]);
- X }
- X if (! file_re)
- X return(ERROR_MASK);
- X
- X found_files = get_the_files(start_dir, file_re, &num_found);
- X free(file_re);
- X total += num_found;
- X if (num_found)
- X num_found = process_files(found_files, num_found);
- X else {
- X /* What we do at this point depends on exactly what the
- X * file_re is. There are three possible conditions:
- X * 1. It's an existing directory. Print nothing.
- X * 2. It doesn't exist in deleted form, and there are
- X * no wildcards in it. Then we print "not found."
- X * 3. It does't exist, but there are wildcards in it.
- X * Then we print "no match."
- X * None of these are considered error conditions, so we
- X * don't set the error flag.
- X */
- X if (no_wildcards(file_re)) {
- X if (! directory_exists(args[num - 1])) {
- X fprintf(stderr, "%s: %s: not found\n",
- X whoami, args[num - 1]);
- X }
- X }
- X else {
- X fprintf(stderr, "%s: %s: no match\n",
- X whoami, args[num-1]);
- X }
- X }
- X }
- X if (total) {
- X list_files();
- X }
- X if (yield)
- X printf("\nTotal space taken up by file%s: %dk\n",
- X (total == 1 ? "" : "s"), blk_to_k(block_total));
- X return(status);
- X}
- X
- X
- X
- X
- Xchar **get_the_files(start_dir, file_re, number_found)
- Xchar *start_dir, *file_re;
- Xint *number_found;
- X{
- X char **matches;
- X int num_matches;
- X char **found;
- X int num;
- X int i;
- X
- X found = (char **) malloc(0);
- X num = 0;
- X
- X matches = find_matches(start_dir, file_re, &num_matches);
- X if (recursive) {
- X char **recurs_found;
- X int recurs_num;
- X
- X for (i = 0; i < num_matches; free(matches[i]), i++) {
- X if (is_deleted(lastpart(matches[i]))) {
- X found = add_str(found, num, matches[i]);
- X num++;
- X }
- X recurs_found = find_deleted_recurses(matches[i], &recurs_num);
- X add_arrays(&found, &num, &recurs_found, &recurs_num);
- X }
- X }
- X else {
- X struct stat stat_buf;
- X char **contents_found;
- X int num_contents;
- X
- X for (i = 0; i < num_matches; free(matches[i]), i++) {
- X if (is_deleted(lastpart(matches[i]))) {
- X found = add_str(found, num, matches[i]);
- X num++;
- X }
- X if (dirsonly)
- X continue;
- X if (lstat(matches[i], &stat_buf))
- X continue;
- X if ((stat_buf.st_mode & S_IFMT) == S_IFDIR) {
- X contents_found = find_deleted_contents_recurs(matches[i],
- X &num_contents);
- X add_arrays(&found, &num, &contents_found, &num_contents);
- X
- X }
- X }
- X }
- X free(matches);
- X *number_found = num;
- X return(found);
- X}
- X
- X
- X
- X
- X
- X
- Xprocess_files(files, num)
- Xchar **files;
- Xint num;
- X{
- X int i;
- X filerec *leaf;
- X
- X for (i = 0; i < num; i++) {
- X if (! (leaf = add_path_to_tree(files[i]))) {
- X fprintf(stderr, "%s: error adding path to filename tree\n",
- X whoami);
- X exit(1);
- X }
- X
- X free(files[i]);
- X if (! timed_out(leaf, current_time, timev)) {
- X free_leaf(leaf);
- X num--;
- X continue;
- X }
- X block_total += leaf->specs.st_blocks;
- X }
- X free(files);
- X return(num);
- X}
- X
- X
- X
- X
- X
- Xlist_files()
- X{
- X filerec *current;
- X char **strings;
- X int num;
- X
- X strings = (char **) malloc(sizeof(char *));
- X num = 0;
- X if (! strings) {
- X perror(sprintf(error_buf, "%s: list_files", whoami));
- X exit(1);
- X }
- X current = get_root_tree();
- X strings = accumulate_names(current, strings, &num);
- X current = get_cwd_tree();
- X strings = accumulate_names(current, strings, &num);
- X column_array(strings, num, DEF_SCR_WIDTH, 0, 0, 2, 1, 0, 1, stdout);
- X for ( ; num; num--)
- X free(strings[num - 1]);
- X free(strings);
- X return(0);
- X}
- END_OF_FILE
- if test 6087 -ne `wc -c <'lsdel.c'`; then
- echo shar: \"'lsdel.c'\" unpacked with wrong size!
- fi
- # end of 'lsdel.c'
- fi
- echo shar: End of archive 3 \(of 6\).
- cp /dev/null ark3isdone
- MISSING=""
- for I in 1 2 3 4 5 6 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 6 archives.
- rm -f ark[1-9]isdone
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
-
- --
- Please send comp.sources.unix-related mail to rsalz@uunet.uu.net.
-
-
-